/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.tencent.tendon.convert.jsontest;

import com.alibaba.fastjson.JSON;
import com.tencent.tendon.convert.json.JsonConvert;
import java.text.DecimalFormat;

/**
 *
 * @author nbzhang
 */
@SuppressWarnings("unchecked")
public class Performance {

    private static boolean titled = false;

    private static final Runtime runtime = Runtime.getRuntime();

    public static void run(Object record) {
        run(Integer.parseInt(System.getProperty("count", "20000")), record);
    }

    public static <T> void run(int count, Object record) {
        final String formarstring = "%43s%20s%20s%22s%20s%20s%18s";
        if (!titled) {
            titled = true;
            String os = "[" + System.getProperty("os.name") + " " + System.getProperty("os.arch") + "]";
            String java = "[" + System.getProperty("java.runtime.name") + " " + System.getProperty("java.runtime.version") + "]";
            System.out.println();
            System.out.println(String.format("%20s", " ") + os + "  " + java + "  " + "[" + Utility.now() + "]");
            System.out.println(String.format(formarstring, "object-info", "convert-from(ms)", "fastjson-from(ms)", "performance-form", "convert-to(ms)", "fastjson-to(ms)", "performance-to"));
        }
        //----------------------------------------------------------
        final Class<T> clazz = (Class<T>) record.getClass();
        final String convertjson = JsonConvert.convertTo(record);
        JsonConvert.convertFrom(convertjson, clazz);
        String fastjson = null;
        boolean canrun = true;
        try {
            fastjson = JSON.toJSONString(record);
            JSON.parseObject(fastjson, clazz);
        } catch (Exception ex) {
            ex.printStackTrace();
            canrun = false;
        }
        long s1, s2, s3, s4, e1, e2, e3, e4;
        long ms1, ms2, ms3, ms4, me1, me2, me3, me4;
        //----------------------------------------------------------
        gc();
        s1 = System.currentTimeMillis();
        ms1 = runtime.freeMemory();
        for (int i = 0; i < count; i++) {
            JsonConvert.convertFrom(convertjson, clazz);
        }
        me1 = ms1 - runtime.freeMemory();
        e1 = System.currentTimeMillis() - s1;

        gc();
        s3 = System.currentTimeMillis();
        ms3 = runtime.freeMemory();
        for (int i = 0; i < count; i++) {
            JsonConvert.convertTo(record);
        }
        me3 = ms3 - runtime.freeMemory();
        e3 = System.currentTimeMillis() - s3;

        //----------------------------------------------------------
        gc();
        s2 = System.currentTimeMillis();
        ms2 = runtime.freeMemory();
        for (int i = 0; i < count; i++) {
            if (canrun) JSON.parseObject(fastjson, clazz);
        }
        me2 = ms2 - runtime.freeMemory();
        e2 = System.currentTimeMillis() - s2;

        gc();
        s4 = System.currentTimeMillis();
        ms4 = runtime.freeMemory();
        for (int i = 0; i < count; i++) {
            if (canrun) JSON.toJSONString(record);
        }
        me4 = ms4 - runtime.freeMemory();
        e4 = System.currentTimeMillis() - s4;

        //----------------------------------------------------------
        String objstr = clazz.getSimpleName() + "(count:" + formartw(count) + ",size:" + convertjson.length() + ")";
        if (fastjson != null && convertjson.length() == fastjson.length()) {
            System.out.println(String.format(formarstring, objstr, e1, e2, compare(e1, e2), e3, e4, compare(e3, e4)));
        } else {
            System.err.println("json string is different");
            System.err.println("converts : " + convertjson);
            System.err.println("fastjson : " + fastjson);
        }

    }

    private static String formartw(int size) {
        if (size >= 10000) return size / 10000 + "w";
        if (size > 1000) return size / 1000 + "k";
        return "" + size;
    }

    private static String compare(long convert, long fast) {
        String s = convert > fast ? "-" : "";
        double r = (Math.abs(convert - fast) + 0.0) * 100 / Math.min(convert, fast);

        return s + format.format(r) + " %";
    }

    private static void gc() {
        if (true) return;
        System.gc();
        try {
            Thread.sleep(100);
        } catch (InterruptedException ex) {
        }
    }

    static String formartMemory(long size) {
        String s = size > 0 ? "" : "-";
        size = Math.abs(size);
        if (size > 1024 * 1024) return s + format.format(size / (1024 * 1024.0)) + "M";
        if (size > 1024) return s + format.format(size / (1024.0)) + "K";
        return s + size + "B";
    }

    private static final DecimalFormat format = new DecimalFormat("0.00");
}
